package infrastructure;


import domain.annotations.NoMapper;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * sql模板生成器
 * 按照属性生成基本sql语句模板
 *
 * @author wyl
 */
public class SqlBuilder {

    /**
     * 构建添加添加的sql模板
     *
     * @param entityClass 实体class
     * @param tableName   表名
     * @return sql模板字符串
     */
    public static String buildAddSqlTemplate(Class<?> entityClass, String tableName) {
        StringBuilder sb = new StringBuilder();
        sb.append("insert into");
        sb.append(" ");
        sb.append(tableName);
        //拼接表字段
        sb.append("(");
        Field[] fields = entityClass.getDeclaredFields();
        List<String> propNames = Arrays.stream(fields)
                .filter(f -> !f.isAnnotationPresent(NoMapper.class))
                .map(Field::getName)
                .collect(Collectors.toList());
        sb.append(String.join(",", propNames));
        sb.append(")");
        //拼接表字段完成
        sb.append(" ");
        //拼接values
        sb.append("values(");
        for (int j = 0; j < propNames.size(); j++) {
            sb.append("?");
            if (j != propNames.size() - 1) {
                sb.append(",");
            }
        }
        sb.append(")");
        //拼接values完成
        return sb.toString();
    }

    /**
     * 生成按标识符删除实体的sql
     *
     * @param tableName      表名
     * @param identifierName 标识符列名
     * @return sql模板字符串
     */
    public static String buildDeleteByIdSqlTemplate(String tableName, String identifierName) {
        StringBuilder sb = new StringBuilder();
        sb.append("delete from");
        sb.append(" ");
        sb.append(tableName);
        sb.append(" ");
        //条件拼接
        sb.append("where");
        sb.append(" ");
        sb.append(identifierName);
        sb.append("=?");
        return sb.toString();
    }

    /**
     * 生成修改实体的sql条件为标识符
     *
     * @param entityClass    实体class
     * @param tableName      表名
     * @param identifierName 标识符列名
     * @return sql模板字符串
     */
    public static String buildUpdateSqlTemplate(Class<?> entityClass, String tableName, String identifierName) {
        StringBuilder sb = new StringBuilder();
        sb.append("update");
        sb.append(" ");
        sb.append(tableName);
        sb.append(" ");
        sb.append("set");
        sb.append(" ");
        //拼接set...
        Field[] fields = entityClass.getDeclaredFields();
        List<String> props = Arrays.stream(fields).filter(f ->
                !f.isAnnotationPresent(NoMapper.class)
                        && !f.getName().equals(identifierName))
                .map(f -> f.getName() + "=?")
                .collect(Collectors.toList());
        sb.append(String.join(",", props));
        //拼接set...完成
        sb.append(" ");
        //条件拼接
        sb.append("where");
        sb.append(" ");
        sb.append(identifierName);
        sb.append("=?");
        return sb.toString();
    }

    /**
     * 生成查询所有实体的sql
     *
     * @param entityClass 实体class
     * @param tableName   表名
     * @return sql字符串
     */
    public static String buildQueryAllSqlTemplate(Class<?> entityClass, String tableName) {
        StringBuilder sb = new StringBuilder();
        sb.append("select");
        sb.append(" ");
        Field[] fields = entityClass.getDeclaredFields();
        //拼接查询的字段
        List<String> propNames = Arrays.stream(fields)
                .filter(f -> !f.isAnnotationPresent(NoMapper.class))
                .map(Field::getName)
                .collect(Collectors.toList());
        sb.append(String.join(",", propNames));
        //拼接查询字段完成
        sb.append(" ");
        sb.append("from");
        sb.append(" ");
        sb.append(tableName);
        return sb.toString();
    }

    /**
     * 生成按标识符查询实体的sql
     *
     * @param entityClass 实体class
     * @param tableName   表名
     * @return sql字符串
     */
    public static String buildQueryByIdTemplate(Class<?> entityClass, String tableName, String identifierName) {
        String allSql = buildQueryAllSqlTemplate(entityClass, tableName);
        StringBuilder sb = new StringBuilder(allSql);
        sb.append(" ");
        //条件拼接
        sb.append("where");
        sb.append(" ");
        sb.append(identifierName);
        sb.append("=?");
        return sb.toString();
    }

    /**
     * 生成按属性字段进行过滤的sql
     *
     * @param entityClass 实体Class
     * @param tableName   表名
     * @param propName    属性名
     * @return sql字符串
     */
    public static String buildQueryByPropNameTemplate(Class<?> entityClass, String tableName, String propName) {
        String allSql = buildQueryAllSqlTemplate(entityClass, tableName);
        StringBuilder sb = new StringBuilder(allSql);
        sb.append(" ");
        //条件拼接
        sb.append("where");
        sb.append(" ");
        sb.append(propName);
        sb.append("=?");
        return sb.toString();
    }

}
